package com.roadmap.biz.life.task;

import java.util.Date;
import java.util.List;
import java.util.Vector;

import com.roadmap.biz.common.BaseManager;
import com.roadmap.biz.common.RdcQueryConst;
import com.roadmap.common.BaseConst;
import com.roadmap.common.BaseEntity;
import com.roadmap.common.BaseEnum.ActionType;
import com.roadmap.entities.Execution;
import com.roadmap.entities.LifeGoal;
import com.roadmap.entities.LifeTask;
import com.roadmap.entities.ext.ExecutionExt;
import com.roadmap.exception.ActionNotSupportedException;
import com.roadmap.exception.EntityNotFoundException;
import com.roadmap.exception.InvalidActionException;
import com.roadmap.exception.InvalidQueryException;
import com.roadmap.exception.InvalidValueException;
import com.roadmap.exception.NotAuthorizedException;
import com.roadmap.exception.NotMatchedException;
import com.roadmap.exception.NullObjectException;
import com.roadmap.exception.ServerException;

public class ExecutionManager extends BaseManager {

	public ExecutionManager(String currentUser, String itemOwner) {
		super(currentUser, itemOwner, Execution.class, LifeTask.class);
	}

	@Override
	public void create(BaseEntity entity) throws NullObjectException,
			InvalidValueException, ServerException, InvalidActionException,
			EntityNotFoundException, ActionNotSupportedException,
			NotAuthorizedException {
		checkEntityIsValid(entity);

		Execution exec = (Execution) entity;
		// 查找执行所属的任务
		LifeTask task = (LifeTask) getParant(exec.getTaskId());
		if (task == null) {
			EntityNotFoundException e = new EntityNotFoundException();
			_log.error("Can't find the exection's parent " + exec.getTaskId(),
					e);
			throw e;
		}

		// 只有scheduled和undergoing的任务才能创建执行记录
		if (!canExecBeCreatedForTask(task)) {
			ActionNotSupportedException e = new ActionNotSupportedException();
			_log.error(String.format("The task %s doesn't support the action.",
					task.getId()), e);
			throw e;
		}

		if (task.getStatus() == BaseConst.LIFETASK_STATUS_UNDERGOING) {
			getDbUtil().save(exec);
			getNoticeManager().notifyForEntry(entity, ActionType.CREATE, null);
			return;
		}

		Vector<BaseEntity> vec = new Vector<BaseEntity>();
		vec.add(exec);

		// 更新任务
		task.setUpdatedTime(exec.getUpdatedTime());
		task.setStatus(BaseConst.LIFETASK_STATUS_UNDERGOING);
		task.setRealStartDate(exec.getExecuteDate());
		vec.add(task);

		updateGoal(vec, task.getGoalId(), exec.getExecuteDate(), exec
				.getUpdatedTime());

		getDbUtil().saveOrUpdateEntities(vec);
		getNoticeManager().notifyForEntry(entity, ActionType.CREATE, null);
	}

	private void updateGoal(Vector<BaseEntity> vec, String goalId,
			Date realStartTime, Date updatedTime)
			throws EntityNotFoundException, ServerException,
			ActionNotSupportedException {
		if (goalId == null) {
			return;
		}

		Object[] params = { goalId, getOwnerId(),
				BaseConst.LIFEGOAL_STATUS_DELETED };
		LifeGoal goal = (LifeGoal) getDbUtil().getUniqueEntity(
				RdcQueryConst.HQL_GOAL_BY_USER_ID, params);
		if (goal == null) {
			EntityNotFoundException e = new EntityNotFoundException();
			_log.error(String.format("Goal %s was not found", goalId), e);
			throw e;
		}

		if (!canExecBeCreatedForGoal(goal)) {
			ActionNotSupportedException e = new ActionNotSupportedException();
			String msg = "Only scheduled or undergoing goals support the action.";
			_log.error(msg, e);
			throw e;
		}

		// 更新目标
		if (goal.getStatus() == BaseConst.LIFEGOAL_STATUS_SCHEDULED) {
			goal.setRealStartDate(realStartTime);
			goal.setUpdatedTime(updatedTime);
			goal.setStatus(BaseConst.LIFEGOAL_STATUS_UNDERGOING);
			vec.add(goal);
		}
	}

	private boolean canExecBeCreatedForTask(LifeTask task) {
		if (task == null) {
			return false;
		}

		return task.getStatus() == BaseConst.LIFETASK_STATUS_SCHEDULED
				|| task.getStatus() == BaseConst.LIFETASK_STATUS_UNDERGOING;
	}

	private boolean canExecBeCreatedForGoal(LifeGoal goal) {
		if (goal == null) {
			return false;
		}

		// 只有scheduled或undergoing的计划（目标）允许创建新执行
		return goal.getStatus() == BaseConst.LIFEGOAL_STATUS_UNDERGOING
				|| goal.getStatus() == BaseConst.LIFEGOAL_STATUS_SCHEDULED;
	}

	@Override
	public List getEntitiesOfParent(String parentId) throws ServerException,
			NullObjectException, NotMatchedException, InvalidValueException,
			InvalidQueryException, EntityNotFoundException,
			NotAuthorizedException {
		// 找到相应的任务并检查用户对该任务的访问权限
		Object[] params = { parentId, getOwnerId(),
				BaseConst.LIFETASK_STATUS_DELETED };
		LifeTask task = (LifeTask) getDbUtil().getUniqueEntity(
				RdcQueryConst.HQL_TASK_BY_ID, params);
		if (task == null) {
			EntityNotFoundException e = new EntityNotFoundException();
			_log.error(String.format("Task was not found by ID %s ", parentId));
			throw e;
		}

		if (!checkUserAccess(task)) {
			NotAuthorizedException e = new NotAuthorizedException();
			String msg = String.format(
					"Current user was not allowed to access task %s", parentId);
			_log.error(msg, e);
			throw e;
		}

		params = new Object[] { parentId };
		List list = getDbUtil().executeHQLQuery(RdcQueryConst.HQL_EXEC_BY_TASK,
				params);
		list = getResultsForSpecifiedPage(list);
		
		computeCommentCount(list);
		return list;
	}

	@Override
	public BaseEntity getEntityExt(String entryId) throws NullObjectException,
			InvalidQueryException, ServerException, InvalidValueException,
			EntityNotFoundException, NotMatchedException,
			NotAuthorizedException {
		// 找到执行记录entryId所属的任务
		Object[] params = { entryId, getOwnerId(),
				BaseConst.LIFETASK_STATUS_DELETED };
		List results = (List) getDbUtil().executeHQLQuery(
				RdcQueryConst.HQL_TASK_EXEC_BY_ID, params, 1);
		if (results == null || results.isEmpty()) {
			EntityNotFoundException e = new EntityNotFoundException();
			_log.error(String.format("Execution was not found by ID %s",
					entryId), e);
			throw e;
		}

		LifeTask task = (LifeTask) ((Object[]) results.get(0))[0];
		checkUserAccess(task);

		// 查询所有执行记录
		params = new Object[] { task.getId() };
		List list = getDbUtil().executeHQLQuery(
				RdcQueryConst.HQL_EXECS_BY_TASK, params);

		list = getResultsForSpecifiedPage(list);
		computeCommentCount(list);

		// 创建一个扩展执行类对象
		ExecutionExt ext = new ExecutionExt();
		ext.setTaskId(task.getId());
		ext.setTaskDesc(task.getWhatItIs());
		ext.setBrothers(list);

		return ext;
	}

}
